/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.liquidByte.trafficMustang.server.business;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import org.liquidByte.trafficMustang.server.dataModel.*;
import org.liquidByte.trafficMustang.server.services.*;
import org.liquidByte.trafficMustang.server.webService.dto.MainDTO;
import org.liquidByte.trafficMustang.server.webService.dto.MensagemDTO;
import org.liquidByte.trafficMustang.server.webService.dto.UpdatesDTO;

/**
 *
 * @author Alexandre
 */
@Stateless
public class MainBO implements MainService {
    
    //<editor-fold defaultstate="collapsed" desc="Updates Handler">
    private static final Object syncObject = new Object();
    private static HashMap<Integer, UpdatesDTO> updates;
    
    static {
        MainBO.updates = new LinkedHashMap<Integer, UpdatesDTO>();
    }
    
    private static UpdatesDTO peekOrCreateUpdate(Integer usrId) {
        if (usrId != null) {
            synchronized(MainBO.syncObject) {
                UpdatesDTO dto = MainBO.updates.get(usrId);
                if (dto == null) {
                    dto = new UpdatesDTO();
                    MainBO.updates.put(usrId, dto);
                }
                return dto;
            }
        }
        return null;
    }
    
    private static UpdatesDTO getUpdate(Integer usrId) {
        if (usrId != null) {
            synchronized(MainBO.syncObject) {
                UpdatesDTO dto = MainBO.updates.get(usrId);
                if (dto != null) {
                    MainBO.updates.remove(usrId);
                }
                return dto;
            }
        }
        return null;
    }
    
    private static List<MensagemDTO> getMessages(Integer usrId) {
        synchronized (MainBO.syncObject) {
            UpdatesDTO dto = MainBO.updates.get(usrId);
            if (dto != null) {
                List<MensagemDTO> msgs = dto.getPutMensagem();
                dto.setPutMensagem(null);
                return msgs;
            }
            return null;
        }
    }
    
    private static boolean remove(Integer forUsr) {
        if (forUsr != null) {
            synchronized (MainBO.syncObject) {
                return MainBO.updates.remove(forUsr) != null;
            }
        } else {
            return false;
        }
    }
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="EJB Injection">
    @EJB
    private LoginService login;
    @EJB
    private TrechoService trecho;
    @EJB
    private DeslocamentoService deslocamento;
    @EJB
    private AvaliacaoService avaliacao;
    @EJB
    private ConverterService converter;
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="Business Methods">
    public MainDTO get() throws BusinessException {
        Usuario usr = this.login.getUsuario();
        PerfilUsuario perfil = this.login.getPerfilUsuario();
        if (usr == null) {
            throw new BusinessException("Não foi possível identificar o usuário atual");
        }
        if (perfil == null){
            throw new BusinessException("Perfil de usuário está indefinido");
        }

        MainDTO main = new MainDTO();
        main.setPerfil(perfil.getDescription());
        main.setPerfilModificavel(true);        
        
        synchronized (MainBO.syncObject) {
            main.setMensagem(MainBO.getMessages(usr.getUsrId()));
            MainBO.remove(usr.getUsrId());
        }
        if (perfil == PerfilUsuario.MOTORISTA) {
            Motorista mot = usr.getMotorista();

            main.setDeslocamentoInformavel(!this.deslocamento.existePendencia(mot));
            main.setTrechoRequisitavel(false);

            main.setDeslocamento(this.converter.getDeslocamento().convert(this.deslocamento.getPendente(mot)));
            main.setAceite(this.converter.getTrecho().convert(this.trecho.getPendente(mot)));
            main.setAvaliacao(this.converter.getAvaliacao().convert(this.avaliacao.getPendente(mot.getUsuario())));
        } else {
            Passageiro pasg = usr.getPassageiro();

            main.setDeslocamentoInformavel(false);
            main.setTrechoRequisitavel(!this.trecho.existePendencia(pasg));

            main.setAvaliacao(this.converter.getAvaliacao().convert(this.avaliacao.getPendente(pasg.getUsuario())));
            main.setTrecho(this.converter.getTrecho().convert(this.trecho.getPendente(pasg)));
        }
        return main;
    }
    
    public void alternarPerfil() throws BusinessException {
        PerfilUsuario perfil = this.login.getPerfilUsuario();
        Usuario usr = this.login.getUsuario();
        if (perfil == PerfilUsuario.MOTORISTA) {
            if (this.deslocamento.existePendencia(usr.getMotorista())) {
                throw new BusinessException("Existem deslocamentos pendentes");
            } else {
                this.login.setPerfilUsuario(PerfilUsuario.PASSAGEIRO);
            }
        } else if (perfil == PerfilUsuario.PASSAGEIRO) {
            if (this.trecho.existePendencia(usr.getPassageiro())) {
                throw new BusinessException("Existem trechos pendentes");
            } else {
                this.login.setPerfilUsuario(PerfilUsuario.MOTORISTA);
            }
        } else {
            throw new BusinessException("Perfil de usuário está indefinido");
        }
    }
    
    public UpdatesDTO getUpdates() throws BusinessException {
        Usuario usr  = this.login.getUsuario();
        if (usr == null) {
            return null;
        } else {
            return MainBO.getUpdate(usr.getUsrId());
        }
    }
    public void messagePut(Usuario usuario, String titulo, String descricao) {
        if (usuario != null) {
            MensagemDTO mensagem = null;
            if ((titulo != null && !titulo.isEmpty()) || (descricao != null && !descricao.isEmpty())) {
                mensagem = new MensagemDTO(titulo, descricao);
            }
            if (mensagem != null) {
                synchronized(MainBO.syncObject) {
                    MainBO.peekOrCreateUpdate(usuario.getUsrId()).getPutMensagem().add(mensagem);
                }
            }
        }
    }

    public void trechoPut(Passageiro usuario, Trecho trecho) {
        if (trecho != null) {
            synchronized (MainBO.syncObject) {
                MainBO.peekOrCreateUpdate(usuario.getUsrId()).getPutTrecho().add(this.converter.getTrecho().convert(trecho));
            }
        }
    }

    public void trechoRemove(Passageiro usuario, Trecho trecho) {
        if (trecho != null) {
            synchronized (MainBO.syncObject) {
                MainBO.peekOrCreateUpdate(usuario.getUsrId()).getRemoveTrecho().add(this.converter.getTrecho().convert(trecho));
            }
        }
    }

    public void aceitePut(Motorista usuario, Trecho trecho) {
        if (trecho != null) {
            synchronized (MainBO.syncObject) {
                MainBO.peekOrCreateUpdate(usuario.getUsrId()).getPutAceite().add(this.converter.getTrecho().convert(trecho));
            }
        }
    }

    public void avaliacaoPut(Usuario usuario, Avaliacao avaliacao) {
        if (avaliacao != null) {
            synchronized (MainBO.syncObject) {
                MainBO.peekOrCreateUpdate(usuario.getUsrId()).getPutAvaliacao().add(this.converter.getAvaliacao().convert(avaliacao));
            }
        }
    }

    public void aceiteRemove(Motorista usuario, Trecho trecho) {
        if (trecho != null) {
            synchronized (MainBO.syncObject) {
                MainBO.peekOrCreateUpdate(usuario.getUsrId()).getRemoveAceite().add(this.converter.getTrecho().convert(trecho));
            }
        }
    }
    //</editor-fold>
}
